package com.wlps.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wlps.contant.Contant;
import com.wlps.entity.CommodityWarehouse;
import com.wlps.entity.Warehouse;
import com.wlps.mapper.CommodityMapper;
import com.wlps.mapper.CommodityWarehouseMapper;
import com.wlps.mapper.PurchaseReceiptMapper;
import com.wlps.mapper.WarehouseMapper;
import com.wlps.result.ResultPageVo;
import com.wlps.result.ResultUtils;
import com.wlps.result.ResultVo;
import com.wlps.service.ICommodityWarehouseService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wlps.vo.sendcenter.warehouse.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 商品-库房表(commodity_warehouse)（中间表） 服务实现类
 * </p>
 *
 * @author ZWYZY
 * @since 2020-07-31
 */
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class CommodityWarehouseServiceImpl extends ServiceImpl<CommodityWarehouseMapper, CommodityWarehouse> implements ICommodityWarehouseService, InitializingBean {
    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    CommodityWarehouseMapping commodityWarehouseMapping;

    @Autowired
    PurchaseReceiptMapper purchaseReceiptMapper;

    @Autowired
    CommodityMapper commodityMapper;

    @Autowired
    WarehouseMapper warehouseMapper;

    @Override
    public void afterPropertiesSet() throws Exception {
        initInOutVo();
        initCommodityWarehouse();
        initWarehouseSettingVo();
    }

    /**
     * 初始化缓存
     */
    void initInOutVo() {
        List<InOutVo> inOutVoList = new ArrayList<>();
        if (!redisTemplate.hasKey(Contant.INOUTVOS_KEY)) {
            List<InOutVo> inList = baseMapper.selectByPurchaseReceipt();
            inList.stream().forEach(x -> {
                x.setWarehosueName("中心库房");
                x.setType(0);
            });
            inOutVoList.addAll(inList);
            List<InOutVo> outList = baseMapper.selectByReturnOutOfStock();
            outList.stream().forEach(x -> {
                x.setWarehosueName("中心库房");
                x.setType(1);
            });
            inOutVoList.addAll(outList);
            redisTemplate.opsForValue().set(Contant.INOUTVOS_KEY, inOutVoList, 5, TimeUnit.MINUTES);
            log.info("初始化所有出入库单-------存入缓存数据（5分钟）");
        }

    }

    /**
     * 初始化缓存
     */
    void initCommodityWarehouse() {
        List<CommodityWarehouse> commodityWarehouses;
        if (redisTemplate.hasKey(Contant.COMMODITYWAREHOUSES_KEY)) {
            commodityWarehouses = (List<CommodityWarehouse>) redisTemplate.opsForValue().get(Contant.COMMODITYWAREHOUSES_KEY);
        } else {
            commodityWarehouses = baseMapper.selectList(null);
            redisTemplate.opsForValue().set(Contant.COMMODITYWAREHOUSES_KEY, commodityWarehouses,5,TimeUnit.MINUTES);
            log.info("初始化所有库房商品-------存入缓存数据");
        }
        if (!redisTemplate.hasKey(Contant.COMMODITYWAREHOUSELIST_KEY)) {
            redisTemplate.opsForList().rightPushAll(Contant.COMMODITYWAREHOUSELIST_KEY, commodityWarehouses);
            redisTemplate.expire(Contant.COMMODITYWAREHOUSELIST_KEY,5,TimeUnit.MINUTES);
            log.info("初始化库房商品列表--------存入缓存数据");
        }

    }

    /**
     * 初始化缓存
     */
    void initWarehouseSettingVo() {
        if (!redisTemplate.hasKey(Contant.WAREHOUSESETTINGVOS_KEY)) {
            List<WarehouseSettingVo> warehouseSettingVos = baseMapper.selectByCommodityAndWarehouse();
            warehouseSettingVos.stream().filter(x -> x != null && x.getWarehouse() == null).forEach(x -> x.setIsSetting(false));
            warehouseSettingVos.stream().filter(x -> x != null && x.getWarehouse() != null).forEach(x -> x.setIsSetting(true));

            redisTemplate.opsForValue().set(Contant.WAREHOUSESETTINGVOS_KEY, warehouseSettingVos, 5, TimeUnit.MINUTES);
            log.info("初始化所有商品库房储备设置-------存入缓存数据（5分钟）");
        }

    }

    @Override
    public ResultPageVo<List<InOutVo>> getInOutVo(int pageNum, int pageSize, InOutConditionVo inOutConditionVo) {
        initInOutVo();

        //总条数
        int count;
        //偏移量
        int fromNum;
        //终止量
        int toNum;
        List<InOutVo> inOutVoList = (List<InOutVo>) redisTemplate.opsForValue().get(Contant.INOUTVOS_KEY);
        if (inOutConditionVo == null) {
            //不是条件查询，redis
            count = inOutVoList.size();

        } else {
            Stream<InOutVo> stream = inOutVoList.stream();
            if (inOutConditionVo.getName() != null) {
                String name = inOutConditionVo.getName();
                stream=stream.filter(x -> x != null && name.equals(x.getCommdityName()));
            }
            if (inOutConditionVo.getStartTime() != null) {
                Date date = inOutConditionVo.getStartTime();
                stream=stream.filter(x -> x != null && x.getUpdateTime().after(date));
            }
            if (inOutConditionVo.getEndTime() != null) {
                Date date = inOutConditionVo.getEndTime();
                stream=stream.filter(x -> x != null && x.getUpdateTime().before(date));
            }
            inOutVoList = stream.collect(Collectors.toList());
            count = inOutVoList.size();
        }
        //当前页从第几条开始查
        fromNum = pageSize * (pageNum - 1);
        if(fromNum>=count)
        {
//            sysUserList=null;
        }else{
            //当前页最后第几条
            toNum = fromNum + pageSize >= count ? count : fromNum + pageSize;
            inOutVoList = inOutVoList.subList(fromNum, toNum);
        }
        //当前页最后第几条

        //分页返回值封装
        ResultPageVo resultPageVo = new ResultPageVo("响应成功", 200, (long) pageSize, (long) pageNum, (long) count, inOutVoList);
        return resultPageVo;
    }

    @Override
    public ResultPageVo<List<CurrentNumberVo>> getCurrentNumberVo(int pageNum, int pageSize, String name) {
        initCommodityWarehouse();
        //总条数
        long count;
        List<CommodityWarehouse> commodityWarehouseList;

        if (name == null) {
            //不是条件查询，redis
            count = (Long) redisTemplate.opsForList().size(Contant.COMMODITYWAREHOUSELIST_KEY);
            //当前页从第几条开始查
            long fromNum = pageSize * (pageNum - 1);
            if(fromNum>=count)
            {
                commodityWarehouseList = (List<CommodityWarehouse>) redisTemplate.opsForList().range(Contant.COMMODITYWAREHOUSELIST_KEY, 0, count);

//            sysUserList=null;
            }else{
                //当前页最后第几条
                long toNum = fromNum + pageSize >= count ? count : fromNum + pageSize;
                commodityWarehouseList = (List<CommodityWarehouse>) redisTemplate.opsForList().range(Contant.COMMODITYWAREHOUSELIST_KEY, fromNum, toNum);
            }
            //当前页最后第几条

//            RedisConfig.returnJedis(jedis);

        } else {
            //条件查询，mysql
            Page<CommodityWarehouse> commodityWarehousePage = new Page<>(pageNum, pageSize);
            LambdaQueryWrapper<CommodityWarehouse> queryWrapper = new QueryWrapper<CommodityWarehouse>().lambda().eq(CommodityWarehouse::getProductName, name);
            IPage<CommodityWarehouse> page = this.baseMapper.selectPage(commodityWarehousePage, queryWrapper);
            commodityWarehouseList = page.getRecords();
            count = page.getSize();
        }
        List<CurrentNumberVo> currentNumberVoList = commodityWarehouseMapping.entitysToVos(commodityWarehouseList);
        currentNumberVoList.stream().forEach(x -> x.setWarehouseName("中心库房"));
        //分页返回值封装
        ResultPageVo resultPageVo = new ResultPageVo("响应成功", 200, (long) pageSize, (long) pageNum, count, currentNumberVoList);

        return resultPageVo;
    }

    @Override
    public ResultVo updateWarehouseSettingSaveOrUpdateVo(WarehouseSettingSaveOrUpdateVo warehouseSettingSaveOrUpdateVo) {
        if (warehouseSettingSaveOrUpdateVo.getMaximumCommodity() - warehouseSettingSaveOrUpdateVo.getCurrentNumber() < 0) {
            return ResultUtils.error("当前商品存储量不能大于最大值，请重新录入", 50002);
        }
        if (commodityMapper.selectCommodityByName(warehouseSettingSaveOrUpdateVo.getProductName()) == null) {
            return ResultUtils.error("系统找不到该商品，请先录入商品信息", 50000);
        }
        Warehouse warehouse = warehouseMapper.selectById(1L);
        List<CommodityWarehouse> commodityWarehouseList = (List<CommodityWarehouse>) redisTemplate.opsForValue().get(Contant.COMMODITYWAREHOUSES_KEY);
        Long maxNumber = commodityWarehouseList.stream().filter(x -> x != null && x.getWarehouseId() == 1).mapToLong(CommodityWarehouse::getMaximumCommodity).sum();
        Long compareNumber = warehouse.getMaximumWarehouse() - maxNumber;
        if (compareNumber - warehouseSettingSaveOrUpdateVo.getMaximumCommodity() <= 0) {
            return ResultUtils.error("当前设置的商品储量最大值{" + warehouseSettingSaveOrUpdateVo.getMaximumCommodity() + "}高于库房存量最大值与目前仓库存放商品最大存量总和之差{" + compareNumber + "}", 50001);
        }
        CommodityWarehouse commodityWarehouse = purchaseReceiptMapper.selectCommodityWareHouseByCommodityName(warehouseSettingSaveOrUpdateVo.getProductName(), 1);

        CommodityWarehouse newCommodityWarehouse = new CommodityWarehouse();
        BeanUtils.copyProperties(warehouseSettingSaveOrUpdateVo, newCommodityWarehouse);
        if (commodityWarehouse != null) {
            baseMapper.update(newCommodityWarehouse, new QueryWrapper<CommodityWarehouse>().lambda().eq(CommodityWarehouse::getWarehouseId, warehouseSettingSaveOrUpdateVo.getWarehouseId()).eq(CommodityWarehouse::getProductName, warehouseSettingSaveOrUpdateVo.getProductName()));
        } else {
            baseMapper.insert(newCommodityWarehouse);
        }
        commodityWarehouseUpdateCache();
        return ResultUtils.success("操作成功");
    }

    @Override
    public ResultPageVo<List<WarehouseSettingVo>> getWarehouseSettingVo(int pageNum, int pageSize, String name) {
        initWarehouseSettingVo();
        //总条数
        int count;
        //偏移量
        int fromNum;
        //终止量
        int toNum;
        List<WarehouseSettingVo> warehouseSettingVoList = (List<WarehouseSettingVo>) redisTemplate.opsForValue().get(Contant.WAREHOUSESETTINGVOS_KEY);
        if (name == null) {
            //不是条件查询，redis
            count = warehouseSettingVoList.size();

        } else {
            Stream<WarehouseSettingVo> stream = warehouseSettingVoList.stream();
            stream=stream.filter(x -> x != null && name.equals(x.getProductName()));
            warehouseSettingVoList = stream.collect(Collectors.toList());
            count = warehouseSettingVoList.size();
        }
        //当前页从第几条开始查
        fromNum = pageSize * (pageNum - 1);
        if(fromNum>=count)
        {
//            sysUserList=null;
        }else{
            //当前页最后第几条
            toNum = fromNum + pageSize >= count ? count : fromNum + pageSize;
            warehouseSettingVoList = warehouseSettingVoList.subList(fromNum, toNum);
        }
        //当前页最后第几条

        //分页返回值封装
        ResultPageVo resultPageVo = new ResultPageVo("响应成功", 200, (long) pageSize, (long) pageNum, (long) count, warehouseSettingVoList);
        return resultPageVo;
    }

    /**
     * 更新缓存
     */
    @Async
    public void commodityWarehouseUpdateCache() {
        List<CommodityWarehouse> commodityWarehouseList = baseMapper.selectList(null);
        redisTemplate.opsForValue().set(Contant.COMMODITYWAREHOUSES_KEY, commodityWarehouseList,5,TimeUnit.MINUTES);
        redisTemplate.delete(Contant.COMMODITYWAREHOUSELIST_KEY);
        redisTemplate.opsForList().rightPushAll(Contant.COMMODITYWAREHOUSELIST_KEY, commodityWarehouseList);
        redisTemplate.expire(Contant.COMMODITYWAREHOUSELIST_KEY,5,TimeUnit.MINUTES);
        log.info("所有库房商品-------更新缓存数据");
    }
}
